/*
 * URLValidator.cpp
 *
 *  Created on: Mar 8, 2011
 *      Author: cnwilson
 */


#include "../inc/URLValidator.h"

#include <assert.h>


//Resolve Address
		//Strip off Query and/or fragment
		//Resolve
		//Is it in scope
		//Is it HTML
		//	It's HTML if:
		//		a)end with a '/'
		//		b)contains no period
		//		c)has extension in extenssion array

			ostream &operator<<(ostream &stream, InvalidSiteException *o){
			  stream << o->site << " is not a valid URL";
			  return stream;
			}

			URLValidator::URLValidator(string *baseSite): base(baseSite){
				if (!isResolved(baseSite)){
					throw new InvalidSiteException(baseSite);
				}
				BasePreprocessor(baseSite);
				base = URL(baseSite);
				extension[0]="/";
				extension[1]=".html";
				extension[2]=".htm";
				extension[3]=".shtml";
				extension[4]=".cgi";
				extension[5]=".jsp";
				extension[6]=".asp";
				extension[7]=".aspx";
				extension[8]=".php";
				extension[9]=".pl";
				extension[10]=".cfm";
			}



            URL URLValidator::validateURL(string *addr, URL *curSite){
            	assert(addr!=NULL);
            	string *addrcopy = new string(*addr);
//            	try{
					if(!isResolved(addrcopy))
						if((addrcopy=resolve(addrcopy,curSite))==NULL){
							delete addrcopy;
							addrcopy==NULL;
							throw new InvalidSiteException(addr);
						}
					if(!preProcess(addrcopy)|| !isHTML(addrcopy)){
						delete addrcopy;
						addrcopy==NULL;
						throw new InvalidSiteException(addr);
					}
					URL newURL(addrcopy);

					if(!inScope(&newURL) ){
						delete addrcopy;
						addrcopy==NULL;
						throw new InvalidSiteException(addr);
					}

					delete addrcopy;
					return newURL;
//            	}
//            	catch(InvalidSiteException e){
//            		cout << "Validating Error" << endl;
//            		//delete e;
//            		delete addrcopy;
//            		throw new InvalidSiteException(addr);
//            	}

            }

			bool URLValidator::preProcess(string *addr){

				try {
					string url=string(*addr);
					unsigned garbage= url.find('#');
					if (garbage!=string::npos){
						url=url.substr(0,garbage);
						*addr= string(url);
					}
				} catch (...) {
					cout << "preProcessing Error" << endl;
					return false;
				}


				return true;
			}

			bool URLValidator::isResolved(string *addr){
				return (StringUtil::IsPrefix(*addr,"http://") || StringUtil::IsPrefix(*addr,"file://"));
			}

			string* URLValidator::resolve(string *addr,URL *curSite){
				urlResolver res;
				string *temp= new string(curSite->getAddress());
				addr=res.resolver(temp,addr);
				if (addr==NULL){
					//cout << "Resolving Error" << base << "\t"<< *addr << endl;
				}
				return addr;
			}

			bool URLValidator::isHTML(string *addr){
				unsigned query= addr->find('?');
				string temp=addr->substr(0,query);
				for(int i=0; i<11;i++)
					if(StringUtil::IsSuffix(temp,extension[i]))
						return true;
				return false;
			}

			bool URLValidator::inScope(URL *newURL){
				return base.inScope(*newURL);
			}

			URL URLValidator::getBaseAddr(){
				return base;
			}

			void URLValidator::BasePreprocessor(string *baseSite){
				string &base=*baseSite;
				unsigned slashCount=0;
				int pos=0;
				while(slashCount<3 && pos<base.length()){
					pos++;
					if (base[pos]=='/')
						slashCount++;
				}
				int ptr=(int)(baseSite->find_last_of("/"));

				if(ptr>=pos)
					*baseSite=string(baseSite->substr(0,ptr+1));
			}




